package com.zero.logistics.shiro;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import com.zero.logistics.pojo.User;

/*
 *	@date:2020年4月3日 上午7:23:53
 *	@author:Zero
 *	@version:Future
 *	@description: 
 *
 */
public class MyFormAuthenticationFilter extends FormAuthenticationFilter{
	
	/**
	 * @function: 处理退出后重新登录的页面乱跳转问题
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
			ServletResponse response) throws Exception {
		// 清理乱跳的资源
		WebUtils.getAndClearSavedRequest(request);  
		return super.onLoginSuccess(token, subject, request, response);
	}

	/**
	 * @function: 认证前先获取验证码进行验证
	 * 	 逻辑：比对用户提交的验证码和Session中共享的验证码是否相同（验证码不区分大小写）
	 *  	不相同 ：return false
	 *   	相同：直接调用父类方法，继续父类代码操作
	 */
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		
		//1.获取请求参数(即获取用户输入的验证码)
		String inputVerifyCode = req.getParameter("inputVerifyCode");
		
		//2.从session中获取机器生成的验证码
		String CODE_IN_SESSION = (String) req.getSession().getAttribute("CODE_IN_SESSION");
		
		//3.根据获取到的验证码进行判断和处理
		if (StringUtils.isNotBlank(inputVerifyCode)  && StringUtils.isNotBlank(CODE_IN_SESSION)) {
			// 3.1 如果验证码不匹配，则回显提示信息并返回false, 然后再次请求转发到登录页面
			if (!inputVerifyCode.equalsIgnoreCase(CODE_IN_SESSION)) {
				req.setAttribute("errMsg", "验证码输入错误");
				req.getRequestDispatcher("/login.jsp").forward(req, resp);
				return false;
			}
		} else {
			// 3.2 如果inputVerifyCode为空，也回显提示信息并返回false
			if ("".equals(inputVerifyCode)) {
				req.setAttribute("errMsg", "验证码不能为空");
				req.getRequestDispatcher("/login.jsp").forward(req, resp);
				return false;
			}
		}
		// 4.验证码匹配成功，则直接调用父类方法，继续父类代码操作
		return super.onAccessDenied(request, response);
	}
	
	/**
	 * @function 获取本地保存的cookie名为USER的登录信息
	 */
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		// 1.从请求中获取Shiro的主体
		Subject subject = getSubject(request, response);
		// 2.从subject中获取Shiro框架的session
		Session session = subject.getSession();
		// 3.当主体没有被认证(Session中认证)且主体已经设置了“记住我”
		if (!subject.isAuthenticated() && subject.isRemembered()) {
			// 4.从“记住我”的cookie中获取主体的身份
			User principal = (User)subject.getPrincipal();
			// 5.将身份信息共享到session中去
			session.setAttribute("USER_IN_SESSION", principal);
		}
		// 6.返回“主体是否认证通过” || “主体是否设置了记住我”, 其实就是返回ture
		return subject.isAuthenticated() || subject.isRemembered();
	}
	
}
